#pragma once

#include <iostream>
#include <unordered_map>
#include "Connection.hpp"
#include "Epoller.hpp"

// TcpServer负责对已经就绪的事件进行通知，具体的处理在Connection内部有读写方法
// TcpServer提供对_connections的管理工作
class Reactor // 事件派发器
{
  const static int gnum = 64;

public:
  Reactor() : _isrunning(false)
  {
  }

  // 添加listensock到TcpServer中，TcpServer独立维护Connection对象
  void AddConnection(int fd, uint32_t events, func_t recver, func_t sender, func_t excepter)
  {
    // 1.构建Connection对象
    Connection *conn = new Connection(fd);
    conn->SetEvents(events); // 设置该链接关心什么事件
    conn->Register(recver, sender, excepter);
    conn->SetR(this);

    // 2.向内核中设定对fd的关心
    _epller.AddEvent(conn->Sockfd(), conn->Events());

    // 3.向_connections添加Connection对象
    _connections.insert(std::make_pair(conn->Sockfd(), conn));
  }

  void EnableReadWrite(int sockfd, bool readable, bool writeable)
  {
    uint32_t events = (readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0) | EPOLLET;
    if (ConnectionIsExists(sockfd))
    {
      // 1.修改我们写的connection关心的事件
      _connections[sockfd]->SetEvents(events);

      // 2.添加到内核
      _epller.ModEvent(sockfd, events);
    }
  }
  void RemoveConnection(int sockfd)
  {
    if (!ConnectionIsExists(sockfd))
      return;
    // 1.去掉epoll对该文件fd的关心
    _epller.DelEvent(sockfd);
    // 2.服务器端要关闭sockfd
    _connections[sockfd]->Close();
    // 3.释放connection
    delete _connections[sockfd];
    _connections.erase(sockfd);
  }
  bool ConnectionIsExists(int sockfd)
  {
    auto iter = _connections.find(sockfd);
    return iter != _connections.end();
  }

  void LoopOnce(int timeout)
  {
    int n = _epller.Wait(revs, gnum, timeout);
    for (int i = 0; i < n; i++)
    {
      int sockfd = revs[i].data.fd;
      uint32_t revents = revs[i].events;

      if (revents & EPOLLHUP)
        revents |= (EPOLLIN | EPOLLOUT);
      if (revents & EPOLLERR)
        revents |= (EPOLLIN | EPOLLOUT);
      if (revents & EPOLLIN)
      {
        if (ConnectionIsExists(sockfd) && (_connections[sockfd]->Recver() != nullptr))
        {
          _connections[sockfd]->Recver()(_connections[sockfd]);
        }
      }
      if (revents & EPOLLOUT)
      {
        if (ConnectionIsExists(sockfd) && (_connections[sockfd]->Sender() != nullptr))
        {
          _connections[sockfd]->Sender()(_connections[sockfd]);
        }
      }
    }
  }

  // 事件派发，自己不做处理，交给上层回调
  // 事件派发核心函数
  void Dispatcher()
  {
    _isrunning = true;
    int timeout = 3000;
    while (true)
    {
      LoopOnce(timeout);
      // 处理其他事情
      Debug();
    }
    _isrunning = false;
  }
  void Debug()
  {
    std::cout << "-----------------------------------------------" << std::endl;
    for (auto &connection : _connections)
    {
      std::cout << "fd : " << connection.second->Sockfd() << ", ";
      uint32_t events = connection.second->Events();
      if ((events & EPOLLIN) && (events & EPOLLET))
      {
        std::cout << "EPOLLIN | EPOLLET ";
      }
      if ((events & EPOLLOUT) && (events & EPOLLET))
      {
        std::cout << "EPOLLOUT | EPOLLET ";
      }
      std::cout << std::endl;
    }
    std::cout << "-----------------------------------------------" << std::endl;
  }
  ~Reactor() {}

private:
  std::unordered_map<int, Connection *> _connections; // sockfd为key
  struct epoll_event revs[gnum];
  Epoller _epller; // 对Connection进行管理，epoll模型
  bool _isrunning;
};